/*
* ========== Copyright Header Begin ==========================================
* 
* OpenSPARC T1 Processor File: config.h
* Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* 
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* 
* The above named program is distributed in the hope that it will be 
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* General Public License for more details.
* 
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* 
* ========== Copyright Header End ============================================
*/
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _CONFIG_H
#define	_CONFIG_H

#pragma ident	"@(#)config.h	1.32	06/03/29 SMI"

#ifdef	__cplusplus
extern "C" {
#endif

#include <stdio.h>

#include "list.h"


	/*
	 * Please Note: this file is in support of machine independent
	 * constructors. Do not place anthing in this file that is
	 * machine specific.
	 */

typedef void(*op_funcp)(simcpu_t *sp, xicache_instn_t * xcip);

typedef enum {
	ES_IDLE,
	ES_RESUME,
	ES_RESET,
	ES_SSI,
	ES_JBUS,
	ES_SPOR,
	ES_XIR,
	ES_NIU,
	ES_PCIE
} ext_sig_t;


typedef enum {
	DA_Load	= 0x1,
	DA_Store = 0x2,
	DA_Atomic = 0x3,	/* bit fields - atomic considered load | store */
	DA_Instn = 0x4,
	DA_Other = 0x8
} dev_access_t;

	/*
	 * Virtual function table for each processor
	 */

struct PROC_TYPE {
	char *		proc_type_namep;		/* processor type name */
	bool_t		flag_initialised;		/* true if module initialised */
	bool_t		(*init_module)(proc_type_t *);	/* call to initialise module */

	void		(*parse_proc)(domain_t *, config_proc_t *);
	void		(*init_proc)(domain_t *, config_proc_t *);	/* call back after parsing */
	void		(*dump_proc)(domain_t *, config_proc_t *);	/* dump processor config */

				/*
				 * Execution support functions
				 */

	bool_t		(*regread)(void * pspecp, int regnum, uint64_t * regp);
	bool_t		(*regwrite)(void * pspecp, int regnum, uint64_t val);

	void		(*exec_setup)(simcpu_t * sp);
	void		(*exec_cleanup)(simcpu_t * sp);

	void		(*check_async_event)(simcpu_t * sp);
	void		(*take_exception)(simcpu_t * sp);

#if ERROR_INJECTION
	void		(*error_condition)(simcpu_t * sp, error_conf_t * ep);
#endif
#if ERROR_TRAP_GEN /* { */
	bool_t		(*trigger_error_trap)(simcpu_t * sp);
	void		(*load_error_file)(config_proc_t * cp);
	void 		(*dump_error_active)(config_proc_t * cp);
	void 		(*dump_error_supported)(config_proc_t * cp);
#endif /* ERROR_TRAP_GEN } */

	op_funcp	(*cpu_decode_me)(simcpu_t *sp, xicache_instn_t * xcip, uint32_t instn);

				/* performance measurement callbacks */
	void		(*perf_dump)(void * pspecp);

				/* functions to dump tlb, instruction counts etc */	
	void		(*tlb_dump)(config_proc_t *, bool_t);
	void		(*instn_cnt_dump)(config_proc_t *);

				/*
				 * External interface methods ...
				 * ... thread clean mechanism for delivering
				 * notifications to running cpus.
				 */

	uint64_t	(*ext_signal)(config_proc_t * cp, ext_sig_t sigtype, void *vp);
	int		(*get_cpuid)(simcpu_t *sp);
	void		(*get_pseudo_dev)(simcpu_t *sp, char *dev_namep, void *devp);
	bool_t		(*dev_mem_access)(config_proc_t *cp, tvaddr_t addr, uint8_t *datap, 
					  uint64_t size, dev_access_t type);  
				/*
				 * Principally debugger access methods, but may also get
				 * used for various magic traps ...
				 */
	void *		(*dbgr_attach)(domain_t *, config_proc_t *, char * dbgr_str);
	void		(*dbgr_detach)(void * pspecp);

			/* returns the amount handled - zero on abject failure */
	uint64_t	(*dbgr_mem_read)(void * pspecp, tvaddr_t vaddr, bool_t do_translate, uint8_t * bufp, uint64_t len);
	uint64_t	(*dbgr_mem_write)(void * pspecp, tvaddr_t vaddr, bool_t do_translate, uint8_t * bufp, uint64_t len);
	uint64_t	(*dbgr_mem_clear)(void * pspecp, tvaddr_t vaddr, bool_t do_translate, uint64_t len);

	void		(*dbgr_set_break)(void * pspecp, tvaddr_t vaddr);
	void		(*dbgr_clear_break)(void * pspecp, tvaddr_t vaddr);

	reg_map_t *	reg_mapp;

#if	DEBUG_HOOK	/* { */
	void            *debug_hookp;
	void		*debug_hook_dumpp;
#endif 	/* } DEBUG_HOOK */

#define	CPU_MAGIC	0xc00ef00d
	uint32_t proc_magic;
};


typedef struct dev_child_type {
	void	*child_devicep;	/* could be anything, depends on the parent */
	int	parent_device_id;
} dev_child_type_t;

struct DEV_TYPE {
	char *	dev_type_namep;
	void	(*parse_dev)(config_dev_t *);
	void	(*init_dev)(config_dev_t *);
	void	(*dump_dev)(config_dev_t *);	/* dump device config */

	/* return a pointer (and extent) to the block requested at
	 * offset, if it is cacheable - return 0
	 */
	tpaddr_t (*dev_cacheable)(config_addr_t *,  dev_access_t type, tpaddr_t offset, uint8_t ** cbp);

	bool_t	(*dev_cpu_access)(simcpu_t *, config_addr_t *, tpaddr_t offset, maccess_t op, uint64_t * regp);

#define	DEV_MAGIC	0xc00fe00e
	uint32_t dev_magic;
};

	/*
	 * Holding struct for processor info
	 * This is a processor dependent structure which
	 * ultimately holds the number of simcpu_t that the
	 * processor supports.
	 */

struct CONFIG_PROC {
	proc_type_t *	proc_typep;
	int		proc_id;	/* number of proc within domain */
	void *		procp;		/* processor specific data */
	domain_t *	domainp;	/* this proc's domain */
};


	/*
	 * Similarly do the same for devices ...
	 */

struct CONFIG_ADDR {
	tpaddr_t		baseaddr;
	tpaddr_t		topaddr;
	tpaddr_t		range;
	struct CONFIG_ADDR	*nextp;
	config_dev_t		*config_devp;
};

struct CONFIG_DEV {
	dev_type_t *	dev_typep;
	bool_t		is_implied;	/* is true if this device get auto created by another device etc. */
	domain_t *	domainp;
	int		device_id;	/* device id within domain */
	void *		devp;
	config_addr_t *	addrp;
	config_dev_t *	nextp;
};


struct DOMAIN {
	int		idx;
	uint64_t	sysclkfreq;
	LIST_DEF( procs, config_proc_t );
	struct {				/* linked sorted list not regular LIST */
		int count;
		config_dev_t * listp;
	} device;
	struct {
		int		count;
		config_addr_t	*listp;
	} address;
#if ERROR_INJECTION
	error_conf_t *	errlistp;
#endif
};


struct SYSTEM {
	char *	namep;
	int	idx;
	LIST_DEF( domains, domain_t );
};

struct ERROR_CONFIG {
	uint64_t	cycle;
	uint32_t	type;
	char *		type_namep;
	uint32_t	op;
	char *		op_namep;
	uint8_t		priv;
	char *		priv_namep;
	error_conf_t *	nextp;
	bool_t		npp;
};


/*
 * Configuration support functions
 */

config_addr_t * find_domain_address(domain_t * domainp, tpaddr_t pa);


	/*
	 * The struct that defines the simulator configuration
	 */

typedef struct {
	LIST_DEF( systems, system_t );
} target_config_t;

extern target_config_t target_config;

void init_target_config();

void dump_config(FILE * outp);

void init_config();

	/*
	 * Parser support functions ...
	 */

uint64_t parse_number_assign();
config_dev_t * insert_domain_device(domain_t * domainp, config_dev_t * config_devp);
config_addr_t * insert_domain_address(domain_t * domainp, config_dev_t * config_devp,
				      tpaddr_t baseaddr, tpaddr_t topaddr);

#ifdef	__cplusplus
}
#endif

#endif	/* _CONFIG_H */
